package com.suneee.refund.service.impl;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.suneee.base.config.ServiceConfig;
import com.suneee.base.util.ContextHelper;
import com.suneee.base.util.JsonUtil;
import com.suneee.channel.dao.ChannelDao;
import com.suneee.channel.entity.Channel;
import com.suneee.context.page.Page;
import com.suneee.core.error.Assert;
import com.suneee.core.error.ErrorUtils;
import com.suneee.core.util.StringUtils;
import com.suneee.refund.bean.Condition;
import com.suneee.refund.bean.ViewRefundApplyWrap;
import com.suneee.refund.dao.RefundApplyDao;
import com.suneee.refund.dao.RefundCheckInfoDao;
import com.suneee.refund.dao.ViewRefundApplyDao;
import com.suneee.refund.entity.RefundApply;
import com.suneee.refund.entity.RefundCheckInfo;
import com.suneee.refund.entity.ViewRefundApply;
import com.suneee.refund.params.RefundParams;
import com.suneee.refund.params.ShopConnAttr;
import com.suneee.refund.service.RefundApplyService;
import com.suneee.refund.service.WarehouseDisposeService;
import com.suneee.resources.ProductError;
import com.suneee.shop.dao.ShopDao;
import com.suneee.shop.entity.Shop;
import com.suneee.store.dao.ShopStockDao;
import com.suneee.store.dao.SkuDao;
import com.suneee.store.dao.SpuDao;
import com.suneee.store.entity.ShopStock;
import com.suneee.store.entity.Spu;
import com.suneee.store.entity.StockDetail;
import com.suneee.store.entity.StockRecord;
import com.suneee.store.resources.StaticParam;
import com.suneee.store.service.IThirdPartyService;
import com.suneee.store.service.ProductService;
import com.suneee.store.service.ThirdPartyFactory;
import com.suneee.trades.dao.OrderLogDao;
import com.suneee.trades.dao.TradesInfoDao;
import com.suneee.trades.dao.TradesOrderDao;
import com.suneee.trades.entity.Shopp;
import com.suneee.trades.entity.TradesInfo;
import com.suneee.trades.entity.TradesOrder;
import com.suneee.trades.resource.BusiType;
import com.suneee.trades.service.TradesInfoService;
import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.FileItem;
import com.taobao.api.TaobaoClient;
import com.taobao.api.domain.Refund;
import com.taobao.api.request.RefundGetRequest;
import com.taobao.api.request.RpReturngoodsRefillRequest;
import com.taobao.api.request.RpReturngoodsRefuseRequest;
import com.taobao.api.response.RefundGetResponse;
import com.taobao.api.response.RpReturngoodsRefillResponse;
import com.taobao.api.response.RpReturngoodsRefuseResponse;

@Service("api-warehouseDispose")
public class WarehouseDisposeServiceImpl implements WarehouseDisposeService {

	@Autowired
	private ViewRefundApplyDao viewRefundApplyDao;

	@Autowired
	private RefundCheckInfoDao refundCheckInfoDao;

	@Autowired
	private RefundApplyDao refundApplyDao;
	
	@Autowired
	private RefundApplyService refundApplyService;
	
	@Autowired
	private TradesInfoDao tradesInfoDao;
	
	@Autowired
	private TradesInfoService tradesInfoService;
	
	@Autowired
	private TradesOrderDao tradesOrderDao;
	
	@Autowired
	private ProductService productService;
	
	@Autowired
	private ShopStockDao shopStockDao;
	
	@Autowired
	private SkuDao skuDao;
	
	@Autowired
	private ShopDao shopDao;
	
	@Autowired
	public OrderLogDao orderLogDao;
	
	@Autowired
	public SpuDao spuDao;
	
	@Autowired
	private ChannelDao channelDao;

	@Override
	public Page<ViewRefundApplyWrap> getNotCheckedList(Condition bean) {
		if (bean == null) {
			bean = new Condition();
		}
		bean.setEnterpriseCode(ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode());
		Page<Map<String,Object>> page = viewRefundApplyDao.getNotCheckedList(bean);
		Page<ViewRefundApplyWrap> resultPage = new Page<>();
		resultPage.setPageNumber(page.getPageNumber());
		resultPage.setOffset(page.getOffset());
		resultPage.setPageSize(page.getPageSize());
		resultPage.setTotalItems(page.getTotalItems());
		resultPage.setTotalPages(page.getTotalPages());
		if (page == null || page.getItems() == null || page.getItems().isEmpty())
			return resultPage;
		List<Map<String,Object>> list = page.getItems();
		List<ViewRefundApplyWrap> wrapList = new ArrayList<>();
		String outSkuId = bean.getOuterSkuId();
		String title = bean.getTitle();
		for (Map<String,Object> map : list) {
			String tid = (String)map.get("tid");
			String afterSaleType = (String)map.get("after_sale_type");
			List<ViewRefundApply> temp = viewRefundApplyDao.getViewRefundApplyBytidNoRefund(tid,afterSaleType,outSkuId,title);
			ViewRefundApplyWrap wrap = new ViewRefundApplyWrap();
			wrap.setBuyerNick(temp.get(0).getBuyerNick());
			wrap.setRefundApplyList(temp);
			wrap.setShopName(temp.get(0).getShopName());
			wrap.setTid(tid);
			wrap.setTradesCreated(temp.get(0).getTradesCreated());
			wrap.setAfterSaleType(temp.get(0).getAfterSaleType());
			wrapList.add(wrap);
		}
		resultPage.setItems(wrapList);
		return resultPage;
	}

	@Override
	public Page<ViewRefundApplyWrap> getCheckedList(Condition bean) {
		if (bean == null) {
			bean = new Condition();
		}
		bean.setEnterpriseCode(ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode());
		Page<Map<String,Object>> page = viewRefundApplyDao.getCheckedList(bean);
		Page<ViewRefundApplyWrap> resultPage = new Page<>();
		resultPage.setPageNumber(page.getPageNumber());
		resultPage.setOffset(page.getOffset());
		resultPage.setPageSize(page.getPageSize());
		resultPage.setTotalItems(page.getTotalItems());
		resultPage.setTotalPages(page.getTotalPages());
		if (page == null || page.getItems() == null || page.getItems().isEmpty())
			return resultPage;
		List<Map<String,Object>> list = page.getItems();
		List<ViewRefundApplyWrap> wrapList = new ArrayList<>();
		String outSkuId = bean.getSkuId();
		String title = bean.getTitle();
		for (Map<String,Object> map : list) {
			String tid = (String)map.get("tid");
			String afterSaleType = (String)map.get("after_sale_type");
			List<ViewRefundApply> temp = viewRefundApplyDao.getViewRefundApplyBytidHasRefund(tid,afterSaleType,outSkuId,title);
			ViewRefundApplyWrap wrap = new ViewRefundApplyWrap();
			wrap.setBuyerNick(temp.get(0).getBuyerNick());
			wrap.setRefundApplyList(temp);
			wrap.setShopName(temp.get(0).getShopName());
			wrap.setTid(tid);
			wrap.setTradesCreated(temp.get(0).getTradesCreated());
			wrap.setAfterSaleType(temp.get(0).getAfterSaleType());
			wrapList.add(wrap);
		}
		resultPage.setItems(wrapList);
		return resultPage;
	}
	public RefundCheckInfo mapToRefdInfo(Map<String,Object> paramMap)
	{
		RefundCheckInfo refundCheckInfo = new RefundCheckInfo();
		if(!StringUtils.isNull(paramMap.get("buyerPackageCode")))
		{
			refundCheckInfo.setBuyerPackageCode(paramMap.get("buyerPackageCode").toString());	
		}
		if(!StringUtils.isNull(paramMap.get("checkPics")))
		{
			refundCheckInfo.setCheckPics(paramMap.get("checkPics").toString());
		}
		if(!StringUtils.isNull(paramMap.get("checkResult")))
		{
			refundCheckInfo.setCheckResult(paramMap.get("checkResult").toString());
		}
		if(!StringUtils.isNull(paramMap.get("num")))
		{
			refundCheckInfo.setNum(Integer.parseInt(paramMap.get("num").toString()));
		}
		if(!StringUtils.isNull(paramMap.get("logisticsCode")))
		{
			refundCheckInfo.setLogisticsCode(paramMap.get("logisticsCode").toString());
		}
		if(!StringUtils.isNull(paramMap.get("outerSkuId")))
		{
			refundCheckInfo.setOuterSkuId(paramMap.get("outerSkuId").toString());
		}
		if(!StringUtils.isNull(paramMap.get("realAmount")))
		{
			refundCheckInfo.setRealAmount(Integer.parseInt(paramMap.get("realAmount").toString()));
		}
		if(!StringUtils.isNull(paramMap.get("refundId")))
		{
			refundCheckInfo.setRefundId(paramMap.get("refundId").toString());
		}
		if(!StringUtils.isNull(paramMap.get("remark")))
		{
			refundCheckInfo.setRemark(paramMap.get("remark").toString());
		}
		if(!StringUtils.isNull(paramMap.get("title")))
		{
			refundCheckInfo.setTitle(paramMap.get("title").toString());
		}
		return refundCheckInfo;
	}
	
	public String doValidateErp(Map<String,Object> paramMap)
	{
		if(null == paramMap ||paramMap.size() == 0)
		{
			return "仓库验收对象不能为空";
		}
		if(StringUtils.isNull(paramMap.get("refundId")))
		{
			return "退款申请单号不能为空";
		}
		if(StringUtils.isNull(paramMap.get("logisticsCode")))
		{
			return "快递公司编码不能为空";
		}
		if(StringUtils.isNull(paramMap.get("buyerPackageCode")))
		{
			return "快递单号不能为空";
		}

		// 将erp传入的参数 转换成实体对象 refundCheckInfo
		RefundCheckInfo refundCheckInfo = this.mapToRefdInfo(paramMap);

		// 售后交易信息
		RefundApply apply = refundApplyDao.select(paramMap.get("refundId").toString());

		// 订单交易信息
		TradesInfo info = tradesInfoDao.select(apply.getTid());

		// 店铺信息
		Shop shop = shopDao.select(info.getShopId());

		// 判断是否为退货。若为退货则调用天猫接口回写买家退货快递单号
		if (RefundParams.AFTER_SALE_TYPE_REFUND_REFUND_GOODS.equals(apply.getAfterSaleType())) {
			Object[] args = new Object[2];
			args[0] = refundCheckInfo.getBuyerPackageCode();
			args[1] = refundCheckInfo.getRefundId();
			// 判断买家是否有填写退货快递单号。
			// List<RefundCheckInfo> result = refundCheckInfoDao.selectWhere("
			// buyer_package_code = ? and refund_id = ? ", args);
			// 买家没有填退货快递单号才调用天猫接口回写退货快递单号
			if (StringUtils.isEmpty(apply.getSid())) {
				Boolean flag = false;
				flag = this.tmallReturngoodsRefill(refundCheckInfo);
				if (!flag) {
					return "回写退货运单号失败！";
				}
			}

			// 处理结果为 S004 时
			if (null != refundCheckInfo.getCheckResult()
					&& refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S004)) {
				apply.setCwRefuseProof(refundCheckInfo.getCheckPics());
				this.tmallRefuseRefundGoods(apply);
			}
		}

		if (RefundParams.AFTER_SALE_TYPE_REFUND_CHANGE_GOODS.equals(apply.getAfterSaleType())) {
			// 售后换货流程： 售后换货。 客服提交
			// 换货出库后。流程直接结束(打单发货界面：如果销售单有对应未结束的售后单则该销售单在打单发货界面中不能显示)
			apply.setStatus(RefundParams.ORDER_STATUS_STOCK_HAS_CHECKED);
			if (refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S004)) {
				apply.setProcessStatus(RefundParams.PROCESS_STATUS_DENY);
			} else {
				apply.setProcessStatus(RefundParams.PROCESS_STATUS_PROCESS);
			}

			// 换货 验收结果为 S002可重售 即更新库存同时更新交易订单信息(内部流程不涉及天猫接口)
			// this.canRefund(apply, refundCheckInfo, info);
		}
		// 根据 验收结论字段判断进行逻辑处理 ：S002 完整（可重售） //允许入库
		if (null != refundCheckInfo.getCheckResult()
				&& refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S002)) {
			apply.setFeedbackStatus(RefundParams.FEEDBACK_STATUS_ACCEPT);
			// apply.setStatus(RefundParams.ORDER_STATUS_STOCK_HAS_CHECKED);
			apply.setIsNoticeRefund("1");

			// 回退到店铺仓 同时在此方法中调用天猫库存更新接口增加商品库存
			this.s002AddStock(apply, refundCheckInfo, shop, info);
		} else if (refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S001)
				|| refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S003)) {
			apply.setFeedbackStatus(RefundParams.FEEDBACK_STATUS_ACCEPT);
			// apply.setStatus(RefundParams.PHASE_TYPE_STOCK_DENY);
			apply.setIsNoticeRefund("1");
		} else {
			// apply.setIsNoticeRefund("2");
			apply.setFeedbackStatus(RefundParams.FEEDBACK_STATUS_DENY);
		}

		apply.setFeedbackTime(new Timestamp(System.currentTimeMillis()));
		// apply.setStatus(RefundParams.ORDER_STATUS_STOCK_HAS_CHECKED);
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
		refundCheckInfo.setCreatedAt(timestamp);
		refundCheckInfo.setUpdatedAt(timestamp);
		refundCheckInfo.setOptUserId(ContextHelper.getCurrentLoginInfo().getAdminId().toString());
		refundCheckInfoDao.insert(refundCheckInfo);
		// 设置退货快递运单号
		apply.setSid(refundCheckInfo.getBuyerPackageCode());
		apply.setRefundNums(refundCheckInfo.getRealAmount());
		refundApplyDao.update(apply);

		// 生成订单处理日志
		this.insertOrderLog(apply, refundCheckInfo);
		return "SUCCESS";
	}

	@Override
	@Transactional
	public void doCheck(RefundCheckInfo refundCheckInfo) throws Exception {
		Assert.notNull(refundCheckInfo.getRefundId(), "退款申请单号");
		
		//售后交易信息
		RefundApply apply = refundApplyDao.select(refundCheckInfo.getRefundId());
		
		//订单交易信息
		TradesInfo info = tradesInfoDao.select(apply.getTid());
		
		//店铺信息
		Shop shop = shopDao.select(info.getShopId());
		
		//判断是否为退货。若为退货则调用天猫接口回写买家退货快递单号
		if(RefundParams.AFTER_SALE_TYPE_REFUND_REFUND_GOODS.equals(apply.getAfterSaleType()))
		{
			Object[] args= new Object[2];
			args[0] = refundCheckInfo.getBuyerPackageCode();
			args[1] = refundCheckInfo.getRefundId();
			//判断买家是否有填写退货快递单号。
			//List<RefundCheckInfo> result = refundCheckInfoDao.selectWhere(" buyer_package_code = ? and refund_id = ? ", args);
			//买家没有填退货快递单号才调用天猫接口回写退货快递单号
			if(StringUtils.isEmpty(apply.getSid()))
			{
				Boolean flag = false;
				flag = this.tmallReturngoodsRefill(refundCheckInfo);
				if(!flag)
				{
					throw ErrorUtils.wrap(ProductError.TMALL_HX_FAIL,"回写退货运单号失败！");
				}
			}
			
			//处理结果为 S004 时
			if(null != refundCheckInfo.getCheckResult() && refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S004))
			{
				apply.setCwRefuseProof(refundCheckInfo.getCheckPics());
				this.tmallRefuseRefundGoods(apply);
			}
		}
		
		if(RefundParams.AFTER_SALE_TYPE_REFUND_CHANGE_GOODS.equals(apply.getAfterSaleType()))
		{
			//售后换货流程： 售后换货。 客服提交 换货出库后。流程直接结束(打单发货界面：如果销售单有对应未结束的售后单则该销售单在打单发货界面中不能显示)
			apply.setStatus(RefundParams.ORDER_STATUS_STOCK_HAS_CHECKED);
			if(refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S004))
			{
				apply.setProcessStatus(RefundParams.PROCESS_STATUS_DENY);	
			}
			else
			{
				apply.setProcessStatus(RefundParams.PROCESS_STATUS_PROCESS);	
			}
			
			
			//换货 验收结果为 S002可重售 即更新库存同时更新交易订单信息(内部流程不涉及天猫接口)
			//this.canRefund(apply, refundCheckInfo, info);	
		}
		//根据 验收结论字段判断进行逻辑处理 ：S002 完整（可重售） //允许入库
		if(null != refundCheckInfo.getCheckResult() && refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S002))
		{
			apply.setFeedbackStatus(RefundParams.FEEDBACK_STATUS_ACCEPT);
			//apply.setStatus(RefundParams.ORDER_STATUS_STOCK_HAS_CHECKED);
			apply.setIsNoticeRefund("1");
			
			//回退到店铺仓 同时在此方法中调用天猫库存更新接口增加商品库存
			this.s002AddStock(apply, refundCheckInfo, shop, info);
		}
		else if(refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S001) 
			 || refundCheckInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S003))
		{
			apply.setFeedbackStatus(RefundParams.FEEDBACK_STATUS_ACCEPT);
			//apply.setStatus(RefundParams.PHASE_TYPE_STOCK_DENY);
			apply.setIsNoticeRefund("1");
		}
		else
		{
			//apply.setIsNoticeRefund("2");
			apply.setFeedbackStatus(RefundParams.FEEDBACK_STATUS_DENY);
		}
		
		apply.setFeedbackTime(new Timestamp(System.currentTimeMillis()));
		//apply.setStatus(RefundParams.ORDER_STATUS_STOCK_HAS_CHECKED);
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
		refundCheckInfo.setCreatedAt(timestamp);
		refundCheckInfo.setUpdatedAt(timestamp);
		refundCheckInfo.setOptUserId(ContextHelper.getCurrentLoginInfo().getAdminId().toString());
		refundCheckInfoDao.insert(refundCheckInfo);
		//设置退货快递运单号
		apply.setSid(refundCheckInfo.getBuyerPackageCode());
		apply.setRefundNums(refundCheckInfo.getRealAmount());
		refundApplyDao.update(apply);
		
		//生成订单处理日志
		this.insertOrderLog(apply, refundCheckInfo);
	}
	
	/**
	 * 卖家拒绝退货
	 * 
	 * @param refundApply
	 * @return
	 * @throws Exception
	 */
	private Boolean tmallRefuseRefundGoods(RefundApply refundApply) {
		TradesInfo info = tradesInfoDao.select(refundApply.getTid());
		Map<String, String> shopMap = this.getShopMap(info.getShopId());
		TaobaoClient client = new DefaultTaobaoClient(shopMap.get(ShopConnAttr.SHOP_CONN_PROXURL),shopMap.get(ShopConnAttr.SHOP_CONN_APPKEY), shopMap.get(ShopConnAttr.SHOP_CONN_SECRET));
		RpReturngoodsRefuseRequest req = new RpReturngoodsRefuseRequest();
		req.setRefundId(Long.valueOf(refundApply.getRefundId()));
		req.setRefundPhase(refundApply.getRefundPhase());
		req.setRefundVersion(Long.valueOf(refundApply.getRefundVersion()));
		if (refundApply.getCwRefuseProof() != null && !"".equals(refundApply.getCwRefuseProof())) 
		{
			InputStream ins = this.getProofFile(refundApply.getCwRefuseProof());
			if (ins != null)
			{
				req.setRefuseProof(new FileItem(refundApply.getCwRefuseProof(), ins));
			}
		}
		RpReturngoodsRefuseResponse rsp = null;
		try 
		{
			rsp = client.execute(req, shopMap.get(ShopConnAttr.SHOP_CONN_APPSESSION));
		}
		catch (ApiException e) 
		{
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "调用天猫taobao.rp.returngoods.refuse (卖家拒绝退货)接口失败！");
		}
		if (rsp.getSubMsg() != null)
		{
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "errorCode:" + rsp.getErrorCode() + ","
					+ rsp.getMsg() + ";subCode:" + rsp.getSubCode() + "," + rsp.getSubMsg());
		}
		if (rsp.getMsg() != null)
		{
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "errorCode:" + rsp.getErrorCode() + ","
					+ rsp.getMsg() + ";subCode:" + rsp.getSubCode() + "," + rsp.getMsg());
		}
		return rsp.isSuccess();
	}
	
	/**
	 * 获取店铺信息
	 * @param shopId
	 * @return
	 */
	public Map<String, String> getShopMap(Integer shopId) {
		Shop shop = shopDao.select(shopId);
		String ruleInfo = shop.getRuleInfo();
		Map<String, String> shopMap = JsonUtil.parse(ruleInfo);
		shopMap.put("proxUrl", shop.getProxyURL());
		return shopMap;
	}
	
	/**
	 * 获取凭证图片路径
	 * @param fileName
	 * @return
	 */
	private InputStream getProofFile(String fileName) {
		InputStream inputStream = null;
		HttpURLConnection httpURLConnection = null;
		String path = ContextHelper.getBean("serviceConfig", ServiceConfig.class).getFileUrl() + "image/product/base/"
				+ fileName;
		URL url;
		try {
			url = new URL(path);
			httpURLConnection = (HttpURLConnection) url.openConnection();
			// 设置网络连接超时时间
			httpURLConnection.setConnectTimeout(3000);
			// 设置应用程序要从网络连接读取数据
			httpURLConnection.setDoInput(true);
			httpURLConnection.setRequestMethod("GET");
			int responseCode = httpURLConnection.getResponseCode();
			if (responseCode == 200) {
				// 从服务器返回一个输入流
				inputStream = httpURLConnection.getInputStream();
			}
		} catch (Exception e) {
			inputStream = null;
		}
		return inputStream;
	}
	
	/**
     * 以下属于 调用天猫 更新库存接口 （出库减库存）
	 * @param shop
	 * @param detail
	 * @param shopStock
	 * @param intFlag -1：减库存，1加库存
	 */
	public void callTmallStock(Shop shop,StockDetail detail, ShopStock  shopStock,Integer intFlag)
	{
		 try 
		 {
			//转换连接信息
			Map<String,String> shopMap = JsonUtil.parse(shop.getRuleInfo());
			shopMap.put("url", shop.getProxyURL());
			Map<String,String> paramMap = new HashMap<String, String>();
			paramMap.put("outerId", shopStock.getSkuId().toString());
			paramMap.put("numIid", shopStock.getChannelSpu());
			//入库是加库存 
			Integer quantity = detail.getIncoming()*intFlag;
			paramMap.put("quantity", String.valueOf(quantity));
			IThirdPartyService client = ThirdPartyFactory.getTmallClient();
			//调用tmall更新库存接口
			client.updateStock(shopMap, paramMap);
		 }
		 catch (Exception e) 
		 {
			 throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "天猫库存更新失败。");
		}
	}
	
	/**
	 * 生成订单处理日志
	 * @param apply
	 * @param refundCheckInfo
	 */
	public void insertOrderLog(RefundApply apply,RefundCheckInfo refundCheckInfo)
	{
		if(RefundParams.AFTER_SALE_TYPE_REFUND_REFUND_GOODS.equals(apply.getAfterSaleType()))
		{
			if(RefundParams.FEEDBACK_STATUS_ACCEPT.equals(apply.getFeedbackStatus()))
			{
				orderLogDao.insert(tradesInfoService.createOrderLog(apply.getTid(), "1",
						ContextHelper.getCurrentLoginInfo().getAdminId(), 
						"仓库验货通过,同意入库",BusiType.ORDER_REFUND_GOODS.name(),"成功",refundCheckInfo.getRemark()));
			}
			else
			{
				orderLogDao.insert(tradesInfoService.createOrderLog(apply.getTid(), "1",
						ContextHelper.getCurrentLoginInfo().getAdminId(), 
						"仓库验货不通过,拒绝入库",BusiType.ORDER_REFUND_GOODS.name(),"成功",refundCheckInfo.getRemark()));
			}
		}
		if(RefundParams.AFTER_SALE_TYPE_REFUND_CHANGE_GOODS.equals(apply.getAfterSaleType())){
			if(RefundParams.FEEDBACK_STATUS_ACCEPT.equals(apply.getFeedbackStatus()))
			{
				orderLogDao.insert(tradesInfoService.createOrderLog(apply.getTid(), "1",
						ContextHelper.getCurrentLoginInfo().getAdminId(), 
						"仓库验货通过,同意入库",BusiType.ORDER_CHANGE_GOODS.name(),"成功",refundCheckInfo.getRemark()));
			}
			else
			{
				orderLogDao.insert(tradesInfoService.createOrderLog(apply.getTid(), "1",
						ContextHelper.getCurrentLoginInfo().getAdminId(), 
						"仓库验货不通过,拒绝入库",BusiType.ORDER_CHANGE_GOODS.name(),"成功",refundCheckInfo.getRemark()));
			}
		}	
	}
	
	/**
	 * 根据 验收结论字段判断进行逻辑处理 ：S002 完整（可重售） //允许入库
	 * 更新店铺库存，生成入库记录
	 * @param apply
	 * @param refundCheckInfo
	 * @param shop
	 * @param info
	 */
	public void s002AddStock(RefundApply apply,RefundCheckInfo refundCheckInfo,Shop shop,TradesInfo info)
	{
		//回退到店铺仓
		String enterpriseCode = ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode();
		ShopStock sStock = shopStockDao.getByShopIdSkuIdEpCode(Integer.valueOf(refundCheckInfo.getOuterSkuId()), enterpriseCode, info.getShopId());
		if(null == sStock)
		{
			throw ErrorUtils.wrap(ProductError.SHOP_INVENTORY_SHORTAGE, "没有库存数据");
		}
			sStock.setStock(sStock.getStock() + refundCheckInfo.getRealAmount());
		//生成入库记录
		StockRecord record = new StockRecord();
		record.setRecordType(StaticParam.D_STOCK_TYPE_IN);
		record.setCreateUserId(ContextHelper.getCurrentLoginInfo().getAdminId());
		record.setCreateTime(new Timestamp(System.currentTimeMillis()));
		if(shop != null)
		{
			record.setRelevantStoreId(shop.getShopId());
			record.setOperateStoreId(shop.getShopId());
			Channel channel = channelDao.getChannelByChannelCode(shop.getChannelCode());
			if(channel != null){
				record.setChannelCode(channel.getChannelCode());
				record.setOperateChannelCode(channel.getChannelCode());
				record.setRelevantChannelCode(channel.getChannelCode());//关联仓库所属渠道
			}
		}
		
		if(RefundParams.AFTER_SALE_TYPE_REFUND_REFUND_GOODS.equals(apply.getAfterSaleType()))
		{
			record.setStockType(StaticParam.STORE_IN_OF_REFUND_GOODS);
		}
		if(RefundParams.AFTER_SALE_TYPE_REFUND_CHANGE_GOODS.equals(apply.getAfterSaleType()))
		{
			record.setStockType(StaticParam.STORE_IN_OF_CHANGE);
		}
		record.setRemark(refundCheckInfo.getRemark());
		record.setEnterpriseCode(ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode());
		List<StockDetail> tempList = new ArrayList<>();
		StockDetail detail = new StockDetail();
		detail.setSpuId(sStock.getSpuId());
		detail.setSkuId(sStock.getSkuId());
		detail.setIncoming(refundCheckInfo.getRealAmount());
		detail.setPrice(sStock.getPrice());
		detail.setStatus(StaticParam.IN_STATUS_DONE);
		tempList.add(detail);
		record.setStockDetailList(tempList);
		//同步天猫库存(增加回退商品的库存)
		Map<String,Object> params = new HashMap<>();
		params.put("shopStock", sStock);
		params.put("stockDetail", detail);
		try 
		{
			refundApplyService.updateOutStoreStock(params);
		}
		catch (Exception e) 
		{
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "更新外部商城库存失败！");
		}
		//更新库存数据
		shopStockDao.update(sStock);
		
		//生成入库单数据
		productService.insertStockRecord(record, StaticParam.IN_FLAG);
		
		//以下属于 调用天猫 更新库存接口 （出库减库存）
		//this.callTmallStock(shop,detail,sStock,1);
	}
	
	/**
	 * 换货 验收结果为 S002可重售 即更新库存同时更新交易订单信息(内部流程不涉及天猫接口)
	 * @param apply
	 * @param refundCheckInfo
	 * @param info
	 */
	public void canRefund(RefundApply apply,RefundCheckInfo refundCheckInfo,TradesInfo info)
	{	
			TradesOrder dto = new TradesOrder();
			dto.setTid(apply.getTid());
			String[] strArr = apply.getSkuStr().split("\\|");
			String iidSku = strArr[0];
			dto.setSkuId(iidSku);
			TradesOrder nOrder = tradesOrderDao.getTradesOrder(dto);
//			nOrder.setIsChanged(true);
			tradesOrderDao.update(nOrder);
			
			String enterpriseCode = ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode();
			ShopStock sStock = shopStockDao.getByShopIdSkuIdEpCode(Integer.valueOf(apply.getChangeSkuCode()), enterpriseCode, info.getShopId());
			nOrder.setOuterSkuId(String.valueOf(sStock.getSkuId()));
			nOrder.setSkuId(String.valueOf(sStock.getChannelSku()));
			nOrder.setNumIid(sStock.getChannelSpu());
			nOrder.setNum(refundCheckInfo.getRealAmount());
			Spu spu = spuDao.select(sStock.getSpuId());
			nOrder.setTitle(spu.getTitle());
			nOrder.setPrice(String.valueOf(sStock.getPrice()));
			nOrder.setStatus(RefundParams.ORDER_STATUS_WAIT_BUYER_CONFIRM_GOODS);
			nOrder.setOrderId(null);
			nOrder.setIsAfterSale(0);
//			nOrder.setIsNew(true);
//			nOrder.setIsChanged(null);
			tradesOrderDao.insert(nOrder);
	}

	@Override
	@Transactional
	public void doSendGoodsOfChange(RefundApply apply) {
		// TODO Auto-generated method stub
		Assert.notNull(apply,"apply参数");
		Assert.notNull(apply.getTid(),"需要换货的淘宝订单号");
		Assert.notNull(apply.getRefundId(), "换货申请单号");
		apply = refundApplyDao.select(apply.getRefundId());
		TradesInfo tradesInfo = tradesInfoDao.getTradesInfo(apply.getTid());
		RefundCheckInfo checkedInfo = refundCheckInfoDao.getCheckInfoByRefundId(apply.getRefundId());
		Shop shop = shopDao.select(tradesInfo.getShopId());
		String companyCode = tradesInfo.getCompanyCode();
		// 生成发货单
		Shopp shopp = tradesInfoService.createShopp(ContextHelper.getCurrentLoginInfo().getAdminId(), companyCode);
		
		//获取订单明细
		TradesOrder temp = new TradesOrder();
		temp.setTid(apply.getTid());
		temp.setOuterSkuId(apply.getChangeSkuCode());
		TradesOrder achieve = tradesOrderDao.getOrderDetail(temp);
		if(null == achieve)
		{
			throw ErrorUtils.wrap(ProductError.CREATE_ORDER_FAILED, "订单明细为空");
		}
		achieve.setRefundId(apply.getRefundId());
		List<TradesOrder> achieveOrders = new ArrayList<>();
		achieveOrders.add(achieve);
		//生成发货单明细
		tradesInfoService.createShoppDetail(achieveOrders, shopp.getShoppId());
		apply.setShoppId(shopp.getShoppId());
		apply.setStatus(RefundParams.ORDER_STATUS_CLOSED);
		apply.setProcessStatus(RefundParams.PROCESS_STATUS_SUCCESS);
		
		//修改售后单状态
		refundApplyDao.update(apply);
		
		if(checkedInfo.getCheckResult().contains(RefundParams.CHECK_RESULT_S004))
		{
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "仓库验收不通过无法换货");
		}
		
			//修改换货的店铺库存
			TradesOrder dto = new TradesOrder();
			dto.setOid(apply.getOid());
			ShopStock shopStock = shopStockDao.getByShopIdSkuIdEpCode(Integer.valueOf(apply.getChangeSkuCode()), 
					ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode(), 
					tradesInfo.getShopId());
			
			//商品出库则需要更新库存(减库存)
			shopStock.setStock(shopStock.getStock() - apply.getGoodsNum());
			shopStockDao.update(shopStock);	
			
			//生成店铺出库单
			StockRecord record = new StockRecord();
			record.setEnterpriseCode(ContextHelper.getCurrentLoginInfo()
					.getEnterprise().getEnterpriseCode());
			record.setRecordType(StaticParam.D_STOCK_TYPE_OUT);
			record.setStockType(StaticParam.STORE_OUT_OF_CHANGE);
			
			if(shop != null)
			{
				record.setOperateStoreId(shop.getShopId());
				record.setRelevantStoreId(shop.getShopId());
				Channel channel = channelDao.getChannelByChannelCode(shop.getChannelCode());
				if(channel != null){
					record.setChannelCode(channel.getChannelCode());
					record.setRelevantChannelCode(channel.getChannelCode());
					record.setOperateChannelCode(channel.getChannelCode());
				}
			}
			
			record.setRemark(StaticParam.STORE_OUT_OF_CHANGE);
			record.setCreateUserId(ContextHelper.getCurrentLoginInfo().getAdminId());
			record.setCreateTime(new Timestamp(System.currentTimeMillis()));
			record.setStockDetailList(new ArrayList<>());
			StockDetail detail = new StockDetail();
			detail.setSpuId(skuDao.select(Integer.valueOf(apply.getChangeSkuCode())).getSpuId());
			detail.setSkuId(Integer.valueOf(apply.getChangeSkuCode()));
			detail.setStatus(StaticParam.OUT_STATUS_DONE);
			
			detail.setIncoming(apply.getGoodsNum());
			if(null != shopStock)
			{
				detail.setPrice(shopStock.getPrice());
			}
			record.getStockDetailList().add(detail);
			productService.insertStockRecord(record,StaticParam.OUT_FLAG);
			//同步天猫库存(减少回退商品的库存)
			detail.setIncoming(0 - detail.getIncoming());
			Map<String,Object> params = new HashMap<>();
			params.put("shopStock", shopStock);
			params.put("stockDetail", detail);
			try {
				refundApplyService.updateOutStoreStock(params);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "更新外部商城库存失败！");
			}
		
		// 生成订单处理日志
		orderLogDao.insert(tradesInfoService.createOrderLog(apply.getTid(), "1",
				ContextHelper.getCurrentLoginInfo().getAdminId(), 
				"客服处理换货出库",BusiType.ORDER_CHANGE_GOODS.name(),"完成","无"));
		
		//以下属于 调用天猫 更新库存接口 （出库减库存）
		//this.callTmallStock(shop,detail,shopStock,-1);
	}

	/**
	 * 卖家回填物流信息
	 * @param refundCheckInfo
	 * @return
	 * @throws Exception
	 */
	private Boolean tmallReturngoodsRefill(RefundCheckInfo refundCheckInfo){
		RefundApply temp = refundApplyDao.select(refundCheckInfo.getRefundId());
		if(temp.getAfterSaleType().equals(RefundParams.AFTER_SALE_TYPE_REFUND_CHANGE_GOODS))
			return true;
		TradesInfo info = tradesInfoDao.select(temp.getTid());
		Map<String,String> shopMap = refundApplyService.getShopMap(info.getShopId());
		TaobaoClient client = new DefaultTaobaoClient(shopMap.get(ShopConnAttr.SHOP_CONN_PROXURL), 
				shopMap.get(ShopConnAttr.SHOP_CONN_APPKEY), 
				shopMap.get(ShopConnAttr.SHOP_CONN_SECRET));
		RpReturngoodsRefillRequest req = new RpReturngoodsRefillRequest();
		req.setRefundId(Long.valueOf(temp.getRefundId()));
		req.setRefundPhase(temp.getRefundPhase());
		req.setLogisticsWaybillNo(refundCheckInfo.getBuyerPackageCode());
		req.setLogisticsCompanyCode(refundCheckInfo.getLogisticsCode());
		RpReturngoodsRefillResponse rsp = null;
		try {
			rsp = client.execute(req, shopMap.get(ShopConnAttr.SHOP_CONN_APPSESSION));
		} catch (ApiException e) {
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE,"同步淘宝操作失败！");
		}
		if(rsp.getSubMsg() != null)
		{
			if("15".equals(rsp.getErrorCode()))
			{
				if("2101".equals(rsp.getSubCode()) || "400".equals(rsp.getSubCode()))
				{
					return true;
				}
				else	
				{
					throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "选择的快递公司跟输入的退货快递单号不匹配");
				}
			}
			else
			{
				throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "errorCode:" + rsp.getErrorCode() + "," + rsp.getMsg() + ";subCode:" + rsp.getSubCode() + "," + rsp.getSubMsg());
			}
		}
		if(rsp.getMsg() != null)
		{
			throw ErrorUtils.wrap(ProductError.ENTERPRISE_NO_ROLE, "errorCode:" + rsp.getErrorCode() + "," + rsp.getMsg() + ";subCode:" + rsp.getSubCode() + ","  + rsp.getMsg());
		}
		return rsp.getIsSuccess();
	}
	
	@Override
	public RefundCheckInfo getCheckedByRefundId(String refundId) {
		RefundCheckInfo refundCheckInfo = refundCheckInfoDao.getCheckInfoByRefundId(refundId);
		RefundApply apply = refundApplyDao.select(refundId);
		if(null != apply)
		{
			refundCheckInfo.settGoodsNum(apply.getGoodsNum());
		}
		return refundCheckInfo;

	}

	@Override
	public ViewRefundApply getViewRefundApplyByTidAndSkuId(String tid,String refundId) {
		Assert.notNull(tid, "订单号");
		Assert.notNull(refundId, "refundId");
		List<ViewRefundApply> list = viewRefundApplyDao.getViewRefundApplyByTidAndSkuId(refundId);
		if (list == null || list.size() == 0) 
		{
			throw ErrorUtils.wrap(ProductError.VIEW_REFUND_APPLY_NO);
		}
		ViewRefundApply viewApply = list.get(0);
		if(!viewApply.getAfterSaleType().equals(RefundParams.AFTER_SALE_TYPE_REFUND_CHANGE_GOODS))
		{
			if(viewApply.getSid() != null && viewApply.getCompanyName() != null)
			{
				return viewApply;
			}
			RefundApply apply = null;
			try 
			{
				apply = this.getRefundDetail(tid, list.get(0).getRefundId());
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
			return viewRefundApplyDao.select(apply.getRefundId());
		}
		return viewApply;
	}

	@Override
	public Page<ViewRefundApplyWrap> getHistoryRefundApplys(Condition condition) {
		if (condition == null)
			condition = new Condition();
		condition.setEnterpriseCode(ContextHelper.getCurrentLoginInfo().getEnterprise().getEnterpriseCode());
		Page<Map<String,Object>> page = viewRefundApplyDao.getHistoryRefundApplys(condition);
		Page<ViewRefundApplyWrap> resultPage = new Page<>();
		resultPage.setPageNumber(page.getPageNumber());
		resultPage.setOffset(page.getOffset());
		resultPage.setPageSize(page.getPageSize());
		resultPage.setTotalItems(page.getTotalItems());
		resultPage.setTotalPages(page.getTotalPages());
		if (page == null || page.getItems() == null || page.getItems().isEmpty())
			return resultPage;
		List<Map<String,Object>> list = page.getItems();
		List<ViewRefundApplyWrap> wrapList = new ArrayList<>();
		String outSkuId = condition.getSkuId();
		String title = condition.getTitle();
		for (Map<String,Object> map : list) {
			String tid = (String)map.get("tid");
			String afterSaleType = (String)map.get("after_sale_type");
			List<ViewRefundApply> temp = viewRefundApplyDao.getHistoryRefundApplyBytid(tid,afterSaleType,outSkuId,title);
			if(temp != null && !temp.isEmpty()){
				ViewRefundApplyWrap wrap = new ViewRefundApplyWrap();
				wrap.setBuyerNick(temp.get(0).getBuyerNick());
				wrap.setRefundApplyList(temp);
				wrap.setShopName(temp.get(0).getShopName());
				wrap.setTid(tid);
				wrap.setTradesCreated(temp.get(0).getTradesCreated());
				wrap.setAfterSaleType(temp.get(0).getAfterSaleType());
				wrapList.add(wrap);
			}
		}
		resultPage.setItems(wrapList);
		return resultPage;
	}

	private RefundApply getRefundDetail(String tid,String refundId) throws Exception{
		TradesInfo info = tradesInfoDao.select(tid);
		Shop shop = shopDao.select(info.getShopId());
		String jsonStr = shop.getRuleInfo();
		String proxUrl = shop.getProxyURL();
		Map<String,String> shopMap = JsonUtil.parse(jsonStr);
		shopMap.put("proxUrl", proxUrl);
		RefundGetResponse detailRsp = this.getDetailRefundApply(shopMap, Long.valueOf(refundId));
		Refund temp = detailRsp.getRefund();
		RefundApply applyTemp = refundApplyDao.select(refundId);
		if(temp.getSid() != null && temp.getCompanyName() != null){
			applyTemp.setSid(temp.getSid());
			applyTemp.setCompanyName(temp.getCompanyName());
			applyTemp.setStatus(temp.getStatus());
			refundApplyDao.update(applyTemp);
		}
		return applyTemp;
	}
	
	private RefundGetResponse getDetailRefundApply(Map<String,String> params,Long refundId) throws Exception{
		TaobaoClient client = new DefaultTaobaoClient(params.get("proxUrl"), params.get("appKey"), params.get("secret"));
		RefundGetRequest req = new RefundGetRequest();
		req.setFields("refund_id, alipay_no, tid, oid, buyer_nick, seller_nick, total_fee, "
				+ "status, created, refund_fee, good_status, has_good_return, payment, "
				+ "reason, desc, num_iid, title, price, num, good_return_time, company_name, "
				+ "sid, address, shipping_type, refund_remind_timeout, refund_phase, "
				+ "refund_version, operation_contraint, attribute, outer_id, sku");
		req.setRefundId(refundId);
		RefundGetResponse rsp = client.execute(req, params.get("appSession"));
		return rsp;
	}
}